// 4. 常⽤类型
// 4.1. 字⾯量
var a; //a的值只能为字符串“你好”
var b; //b的值只能为数字100
// a = '欢迎'//警告：不能将类型“"欢迎"”分配给类型“"你好"”
// b = 200 //警告：不能将类型“200”分配给类型“100”
var gender; //定义⼀个gender变量，值只能为字符串“男”或“⼥”
gender = '男';
// gender = '未知' //不能将类型“"未知"”分配给类型“"男" | "⼥"”
// 4.2. any
// any 的含义是：任意类型，⼀旦将变量类型限制为 any ，那就意味着放弃了对该变量的类型检查。
// 明确的表示aa的类型是any —— 显式的any
var aa;
//以下对aa的赋值，均⽆警告
aa = 100;
aa = '你好';
aa = false;
//没有明确的表示b的类型是any，但TS主动推断了出来 —— 隐式的any
var bb;
//以下对b的赋值，均⽆警告
bb = 100;
bb = '你好';
bb = false;
// 注意点： any 类型的变量，可以赋值给任意类型的变量
/* 注意点：any类型的变量，可以赋值给任意类型的变量 */
var aaa;
var x;
x = aaa; // ⽆警告
// 4.3. unknown
// unknown 的含义是：未知类型。
// 备注1： unknown 可以理解为⼀个类型安全的 any
// 备注2： unknown 适⽤于：开始不知道数据的具体类型，后期才能确定数据的类型
// 设置a的类型为unknown
var a2;
//以下对a的赋值，均正常 a = 100
a2 = false;
a2 = '你好';
// 设置x的数据类型为string
var x2;
// x2 = a2 //警告：不能将类型“unknown”分配给类型“string”
// 若就是想把 a 赋值给 x ，可以⽤以下三种写法：
/*
    // 设置a的类型为unknown
    let a: unknown
    a = 'hello'
    //第⼀种⽅式：加类型判断
    if(typeof a === 'string'){
        x = a }
    //第⼆种⽅式：加断⾔ x = a as string
    //第三种⽅式：加断⾔ x = <string>a
* */
var a3;
a3 = 'hello';
if (typeof a3 === 'string') {
    x2 = a3;
}
var x3;
x3 = a3;
var x5;
x5 = a3;
// 4.4. never
// never 的含义是：任何值都不是，简⾔之就是不能有值， undefined 、 null 、 '' 、 0 都不 ⾏！
// 1. ⼏乎不⽤ never 去直接限制变量，因为没有意义，例如：
/* 指定a的类型为never，那就意味着a以后不能存任何的数据了 */
var a11;
// 以下对a11的所有赋值都会有警告
// a11 = 1
// a11 = true
// a11 = undefined
// a11 = null
// 2. never ⼀般是 TypeScript 主动推断出来的，例如：
// 指定a22的类型为string
var a22;
// 给a22设置⼀个值 a22 = 'hello'
if (typeof a22 === 'string') {
    a22.toUpperCase();
}
else {
    console.log(a22); // TypeScript会推断出此处的a22是never，因为没有任何⼀个值符合此处的逻辑
}
// 3. never 也可⽤于限制函数的返回值
// 限制demo函数不需要有任何返回值，任何值都不⾏，像undeifned、null都不⾏
function demo() {
    throw new Error('程序异常退出');
}
// 4.5. void
// void 的含义是： 空 或 undefined ，严格模式下不能将 null 赋值给 void 类型。
var a33 = undefined;
//严格模式下，该⾏会有警告：不能将类型“null”分配给类型“void”
var b33 = null;
// void 常⽤于限制函数返回值
// ⽆警告
function demo1() { }
// ⽆警告
function demo2() {
    return;
}
// ⽆警告
function demo3() {
    return undefined;
}
// 有警告：不能将类型“number”分配给类型“void”
function demo4() {
    // return 666
}
// 4.6. object 关于 Object 与 object ，直接说结论：在类型限制时， Object ⼏乎不⽤，因为范围太⼤了，⽆ 意义
// 1. object 的含义：任何【⾮原始值类型】，包括：对象、函数、数组等，限制的范围⽐较宽泛，⽤的少。
var a222; //a222的值可以是任何【⾮原始值类型】，包括：对象、函数、数组等
// 以下代码，是将【⾮原始类型】赋给a222，所以均⽆警告
a222 = {};
a222 = { name: '张三' };
a222 = [1, 3, 5, 7, 9];
a222 = function () { };
// 以下代码，是将【原始类型】赋给a，有警告
a222 = null; // 警告：不能将类型“null”分配给类型“object”  ???
a222 = undefined; // 警告：不能将类型“undefined”分配给类型“object” ???
// a222 = 1 // 警告：不能将类型“number”分配给类型“object”
// a222 = true // 警告：不能将类型“boolean”分配给类型“object”
// a222 = '你好' // 警告：不能将类型“string”分配给类型“object”
// 2. Object 的含义： Object 的实例对象，限制的范围太⼤了，⼏乎不⽤。
var a333; //a的值必须是Object的实例对象，
// 以下代码，均⽆警告，因为给a赋的值，都是Object的实例对象 s
a333 = {};
a333 = { name: '张三' };
a333 = [1, 3, 5, 7, 9];
a333 = function () { };
a333 = 1; // 1不是Object的实例对象，但其包装对象是Object的实例
a333 = true; // truue不是Object的实例对象，但其包装对象是Object的实例
a333 = '你好'; // “你好”不是Object的实例对象，但其包装对象是Object的实例
// 以下代码均有警告
a333 = null; // 警告：不能将类型“null”分配给类型“Object” ???
a333 = undefined; // 警告：不能将类型“undefined”分配给类型“Object” ???
// 3. 实际开发中，限制⼀般对象，通常使⽤以下形式
// 限制person对象的具体内容，使⽤【,】分隔，问号代表可选属性
var person;
// 限制car对象的具体内容，使⽤【;】分隔，必须有price和color属性，其他属性不去限制，有 没有都⾏
var car;
// 限制student对象的具体内容，使⽤【回⻋】分隔
var student;
// 以下代码均⽆警告
person = { name: '张三', age: 99 };
console.log(person);
person = { name: '李四' };
console.log(person);
car = { price: 100, color: 'red' };
console.log(car);
car = { price: 100, color: 'red', x: 12, y: true, z: '你好' };
console.log(car);
student = { id: 'xxx001', grade: 333 };
console.log(student);
// student = {id:'xxx001',grade:333,name:'x'}
// 4. 限制函数的参数、返回值，使⽤以下形式
var demoxx;
demoxx = function (x, y) {
    return x + y;
};
console.log(demoxx(1, 3));
// 5. 限制数组，使⽤以下形式
var arr1; // 该⾏代码等价于： let arr1: Array<string>
var arr2; // 该⾏代码等价于： let arr2: Array<number>
arr1 = ['a', 'b', 'c'];
arr2 = [1, 3, 5, 7, 9];
console.log(arr1, arr2);
// 4.7. tuple
// tuple 就是⼀个⻓度固定的数组。
var t;
t = ['hello', 123];
// 警告，不能将类型“[string, number, boolean]”分配给类型“[string, number]”
// t = ['hello',123,false]
console.log(t, typeof (t));
// 4.8. enum
// enum 是枚举
// 定义⼀个枚举
var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Blue"] = 1] = "Blue";
    Color[Color["Black"] = 2] = "Black";
    Color[Color["Gold"] = 3] = "Gold";
})(Color || (Color = {}));
console.log(Color);
// 定义⼀个枚举，并指定其初识数值
var Color2;
(function (Color2) {
    Color2[Color2["Red"] = 6] = "Red";
    Color2[Color2["Blue"] = 7] = "Blue";
    Color2[Color2["Black"] = 8] = "Black";
    Color2[Color2["Gold"] = 9] = "Gold";
})(Color2 || (Color2 = {}));
console.log(Color2);
// 定义⼀个phone变量，并设置对⻬进⾏限制
var phone;
phone = { name: '华为Mate60', price: 6500, color: Color.Red };
console.log(phone);
phone = { name: 'iphone', price: 1000, color: Color.Black };
console.log(phone);
if (phone.color === Color.Black) {
    console.log('手机是黑色的');
}
